package design.onekey.util;

import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName: RedisUtil
 * @Description: redis工具类
 * @author blcloak
 * @date 2020-06-01 08:26:33
 */
@Component
@Slf4j
public class RedisUtil {

	/**
	 * @Fields redisTemplate : redisTemplate注入
	 * @author blcloak
	 * @date 2020-06-01 08:28:22
	 */
	@Autowired
	private RedisTemplate<String, Object> redisTemplate;

	/**
	 * @Title: hasKey
	 * @Description: 判断key是否存在
	 * @param key
	 * @return
	 * @author blcloak
	 * @date 2020-06-01 08:31:47
	 */
	public boolean hasKey(String key) {
		try {
			return redisTemplate.hasKey(key);
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}

	}

	/**
	 * @Title: del
	 * @Description: 删除缓存，可以传一个值 或多个
	 * @param key
	 * @author blcloak
	 * @date 2020-06-01 08:33:00
	 */
	public void del(String... key) {
		if (key != null && key.length > 0) {
			if (key.length == 1) {
				redisTemplate.delete(key[0]);
			} else {
				redisTemplate.delete(CollectionUtils.arrayToList(key));
			}
		}
	}

	/**
	 * @Title: delPattern
	 * @Description: 匹配删除
	 * @param key
	 * @author blcloak
	 * @date 2021-02-02 04:34:44
	 */
	public void delPattern(String key)
	{
		Set<String> keys = redisTemplate.keys(key + "*");
		redisTemplate.delete(keys);
	}

	/**
	 * @Title: get
	 * @Description: 普通缓存获取
	 * @param key
	 * @return
	 * @author blcloak
	 * @date 2020-06-01 08:33:38
	 */
	public Object get(String key) {
		return key == null ? null : redisTemplate.opsForValue().get(key);
	}

	/**
	 * @Title: multiGet
	 * @Description: 获取多个值
	 * @param keys
	 * @return
	 * @author blcloak
	 * @date 2020-08-19 05:57:16
	 */
	public List<Object> multiGet(List<String> keys)
	{
		return keys == null || keys.size() == 0?null:redisTemplate.opsForValue().multiGet(keys);
	}

	/**
	 * @Title: set
	 * @Description: 普通缓存放入
	 * @param key
	 * @param value
	 * @return true成功 false失败
	 * @author blcloak
	 * @date 2020-06-01 08:34:21
	 */
	public boolean set(String key, Object value) {
		try {
			redisTemplate.opsForValue().set(key, value);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * @Title: set
	 * @Description: 普通缓存放入并设置时间
	 * @param key
	 * @param value
	 * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
	 * @return
	 * @author blcloak
	 * @date 2020-06-01 08:35:02
	 */
	public boolean set(String key, Object value, long time) {
		try {
			if (time > 0) {
				redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
			} else {
				set(key, value);
			}
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * @Title: setNx
	 * @Description: 如果不存在则set值，如果存在则不set
	 * @param key
	 * @param value
	 * @return
	 * @author blcloak
	 * @date 2020-11-27 09:16:33
	 */
	public boolean setNx(String key,Object value)
	{
		try {
			Boolean result = redisTemplate.opsForValue().setIfAbsent(key, value);
			if(result != null)
			{
				return result.booleanValue();
			}
		} catch (Exception e) {
			log.error("setNXEX error", e);
		}
		return false;
	}

	/**
	 * @Title: setNx
	 * @Description: 如果不存在则set值，如果存在则不set
	 * @param key
	 * @param value
	 * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
	 * @return
	 * @author blcloak
	 * @date 2020-11-27 07:19:37
	 */
	public boolean setNx(String key,Object value,long time)
	{
		try {
			Boolean result = redisTemplate.opsForValue().setIfAbsent(key, value, time, TimeUnit.SECONDS);
			if(result != null)
			{
				return result.booleanValue();
			}
		} catch (Exception e) {
			log.error("setNXEX error", e);
		}
		return false;
	}

	/**
	 * @Title: getExpire
	 * @Description: 获取key过期时间
	 * @param key
	 * @return
	 * @author blcloak
	 * @date 2020-06-16 09:04:34
	 */
	public Long getExpire(String key) {
		if (StringUtil.isNullOrEmpty(key)) {
			return null;
		}else {
			return redisTemplate.getExpire(key);
		}
	}

	/**
	 * @Title: geoAdd
	 * @Description: 添加geo信息
	 * @param key
	 * @param point
	 * @param member
	 * @author blcloak
	 * @date 2020-07-21 02:37:24
	 */
	public void geoAdd(String key, Point point, Object member) {
		redisTemplate.opsForGeo().add(key, point, member);
	}

//	public void geoGet() {
//		redisTemplate.opsForGeo().geoRadiusByMember(key, member, distance)
//	}

	/**
	 * 指定缓存失效时间
	 * @param key 键
	 * @param time 时间(秒)
	 * @return
	 */
	public boolean expire(String key,long time){
		try {
			if(time>0){
				redisTemplate.expire(key, time, TimeUnit.SECONDS);
			}
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}
	/**
	* @Description: 计数
	* @Author: wzc
	* @Date: 2021/3/5 15:30
	*/
	public Long incr(String key, long liveTime) {
		RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
		Long increment = entityIdCounter.getAndIncrement();

		if ((null == increment || increment.longValue() == 0) && liveTime > 0) {//初始设置过期时间
			entityIdCounter.expire(liveTime, TimeUnit.SECONDS);
		}

		return increment;
	}

//============================set=============================
	/**
	 * 根据key获取Set中的所有值
	 * @param key 键
	 * @return
	 */
	public Set<Object> sGet(String key){
		try {
			return redisTemplate.opsForSet().members(key);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 根据value从一个set中查询,是否存在
	 * @param key 键
	 * @param value 值
	 * @return true 存在 false不存在
	 */
	public boolean sHasKey(String key,Object value){
		try {
			return redisTemplate.opsForSet().isMember(key, value);
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 将数据放入set缓存
	 * @param key 键
	 * @param values 值 可以是多个
	 * @return 成功个数
	 */
	public long sSet(String key, Object...values) {
		try {
			return redisTemplate.opsForSet().add(key, values);
		} catch (Exception e) {
			e.printStackTrace();
			return 0;
		}
	}

	/**
	 * 将set数据放入缓存
	 * @param key 键
	 * @param time 时间(秒)
	 * @param values 值 可以是多个
	 * @return 成功个数
	 */
	public long sSetAndTime(String key,long time,Object...values) {
		try {
			Long count = redisTemplate.opsForSet().add(key, values);
			if(time>0) {
				expire(key, time);
			}
			return count;
		} catch (Exception e) {
			e.printStackTrace();
			return 0;
		}
	}

	/**
	 * 获取set缓存的长度
	 * @param key 键
	 * @return
	 */
	public long sGetSetSize(String key){
		try {
			return redisTemplate.opsForSet().size(key);
		} catch (Exception e) {
			e.printStackTrace();
			return 0;
		}
	}

	/**
	 * 移除值为value的
	 * @param key 键
	 * @param values 值 可以是多个
	 * @return 移除的个数
	 */
	public long setRemove(String key, Object ...values) {
		try {
			Long count = redisTemplate.opsForSet().remove(key, values);
			return count;
		} catch (Exception e) {
			e.printStackTrace();
			return 0;
		}
	}
//============================set=============================
}
